/**
 * 数组去重
 */

let arrayDeduplication = (arr) => {
  let arrValue = [];
  let arrObject = [];
  let arrArray = [];
  arr.forEach((e) => {
    let eleType = Object.prototype.toString.call(e).slice(7, -1);
    if (eleType == "Array") {
      arrArray.push(arrayDeduplication(e));
    } else if (eleType == "Object") {
      arrObject.push(e);
    } else {
      arrValue.push(e);
    }
  });
  arrValue = [...new Set(arrValue)];
  return [...arrValue, ...arrObject, ...arrArray];
};

/**
 * 对象key排序
 */

let objectSort = (obj) => {
  let newObj = {};
  Object.keys(obj)
    .sort((a, b) => a - b)
    .forEach((e) => (newObj[e] = obj(e)));
  return newObj;
};
/**
 * 洗牌算法
 */

let shuffle = (arr, n = arr.length - 1) => {
  let random = Math.floor(Math.random() * n);
  [arr[random], arr[n]] = [arr[n], arr[random]];
  if (n === 0) {
    return arr;
  }
  return shuffle(arr, n - 1);
};

// shuffle([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "j", "Q", "k"]);

/**
 * 累加
 */

let addUpTo = (n, num = 0) => {
  num = n + num;
  n = n - 1;
  if (n === 0) return num;
  return addUpTo(n, num);
};

// addUpTo(10);

/**
 * 组合函数
 */

let compeose = (...fn) => {
  if (fn.length < 1) return (e) => e;
  if (fn.length === 1) return fn[0];
  return fn.reduce(
    (fn1, fn2) =>
      (...args) =>
        fn2(fn1(...args))
  );
};

// let add1 = (x) => x + 1;
// let add2 = (x) => x + 2;
// let add3 = (x) => x + 3;
// let add4 = (x) => x + 4;
// let add5 = (x) => x + 5;
// compeose(add1, add2, add3, add4, add5)(1);

/**
 * template字符替换
 */

let render = (tempale, data) => {
  return tempale.replace(/\{\{(\w+)\}\}/g, function (a, b) {
    return data[b];
  });
};

// let a = {
//   name: '仔',
//   age: '16',
//   sex: '男'
// }
// let str = `大家好，我是{{name}},性别{{sex}},今年{{age}}岁`
// render(str,a)

/**
 *  冒泡排序 比较所有相邻的两个项，如果第一个比第二个大，则交换它们。元素项向上移动至 正确的顺序，就好像气泡升至表面一样
 */

let bubbleSort = (arr) => {
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = 0; j < arr.length - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  return arr;
};

let a = [
  1, 2, 5, 4, 6, 8, 9, 5, 4, 5, 6, 2, 1, 68, 46, 41, 34, 3, 413, 143, 4, 43, 14,
  53,
];
bubbleSort(a);

/**
 * 选择排序  选择排序大致的思路是找到数据结构中的最小值并 将其放置在第一位，接着找到第二小的值并将其放在第二位
 */

let selectionSort = (arr) => {
  for (let i = 0; i < arr.length - 1; i++) {
    let min = i;
    arr.slice(i + 1).forEach((e, index) => {
      if (arr[min] > e) {
        min = index + i + 1;
      }
    });
    if (min != i) {
      [arr[i], arr[min]] = [arr[min], arr[i]];
    }
  }
  return arr;
};
selectionSort(a);

/**
 * 插入排序 插入排序每次排一个数组项，以此方式构建最后的排序数组。
 */

let insertionSort = (arr) => {
  for (let i = 0; i < arr.length; i++) {
    let j = i;
    let a = arr[i];
    while (j > 0 && arr[j - 1] > a) {
      arr[j] = arr[j - 1];
      j--;
    }
    arr[j] = a;
  }
  return arr;
};
insertionSort(a);
/**
 * 希尔排序(Shell's Sort) 插入排序的一种又称“缩小增量排序”
 */
let shellSort = (arr) => {
  return arr;
};
/**
 * 快排 使用分而治之的方法
 */
let Quicksort = (arr) => {
  if (arr.length <= 1) return arr;
  let left = [];
  let right = [];
  let middle = arr.splice(Math.floor(arr.length / 2), 1)[0];
  arr.forEach((e) => (e > middle ? right.push(e) : left.push(e)));
  return [...Quicksort(left), middle, ...Quicksort(right)];
};

/**
 * 计数排序 把值当索引存入
 */
let countingSort = (arr) => {
  let count = [];
  let res = [];
  arr.forEach((e) => {
    if (!count[e]) {
      count[e] = 0;
    }
    count[e]++;
  });
  console.log(count);
  count.forEach((e, i) => {
    if (e && e > 0) {
      res = [...res, ...new Array(e).fill(i)];
    }
  });
  return res;
};
